package sbc.group1.lab1.mozartspaces;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.ListIterator;
import java.util.Set;

import org.mozartspaces.capi3.Capi3AspectPort;
import org.mozartspaces.capi3.CoordinationData;
import org.mozartspaces.capi3.LabelCoordinator;
import org.mozartspaces.capi3.Selector;
import org.mozartspaces.capi3.SubTransaction;
import org.mozartspaces.capi3.Transaction;
import org.mozartspaces.core.Entry;
import org.mozartspaces.core.aspects.AspectResult;
import org.mozartspaces.core.aspects.ContainerIPoint;
import org.mozartspaces.core.requests.WriteEntriesRequest;

import sbc.group1.lab1.common.Engine;

class LabelEnginesContainerAspect extends AbstractDefaultOkContainerAspect {
    
    public static Selector getSelector(Engine.Type type, int count) {
        return LabelCoordinator.newSelector(
                type.name(), 
                count, 
                Engine.Type.class.getCanonicalName());
    }

    public static Selector getSelector(Engine.Type type) {
        return getSelector(type,1);
    }

    public static LabelCoordinator getCoordinator() {
        return new LabelCoordinator(Engine.Type.class.getCanonicalName());
    }

    public static Set<ContainerIPoint> getUsedContainerIPoints() {
        Set<ContainerIPoint> ret = new HashSet<ContainerIPoint>();
        ret.add(ContainerIPoint.PRE_WRITE);
        return ret;
    }
    
    @Override
    public AspectResult preWrite(WriteEntriesRequest request,
            Transaction tx, SubTransaction stx, Capi3AspectPort capi3,
            int executionCount) {
        ListIterator<Entry> iter = request.getEntries().listIterator();
        while (iter.hasNext()) {
            Entry entry = iter.next();
            iter.remove();
            iter.add(createReplacement(entry));
        }
        return AspectResult.OK;
    }

    private Entry createReplacement(Entry entry) {
        LinkedList<CoordinationData> coordinationData = 
            new LinkedList<CoordinationData>();
        for (CoordinationData data : entry.getCoordinationData()) {
            if (data.getName().equals(Engine.Type.class.getCanonicalName())) {
            }else {
                coordinationData.add(data);
            }
        }
        if (entry.getValue() instanceof Engine) {
            Engine engine = (Engine) entry.getValue();
            coordinationData.add(getLabelForEngine(engine));
        }
        return new Entry(entry.getValue(),coordinationData);
    }

    private CoordinationData getLabelForEngine(Engine engine) {
        return getCoordinationData(engine.getType());
    }
    
    private CoordinationData getCoordinationData(Engine.Type type) {
        return LabelCoordinator.newCoordinationData(
                type.name(), 
                Engine.Type.class.getCanonicalName());
    }
}
